<template>
  <div class="SurfaceAnalysis-container">
    <!-- g6 容器 -->
    <!-- 以防数据量过大,加载速度慢,引入 element ui 的 loading -->
    <div
      v-if="!lengthShow"
      id="container"
      v-loading="loading"
      element-loading-text="加载中..."
      element-loading-background="rgba(0, 0, 0, 0.8)"
      style="width: 100%; height: 270px"
    ></div>

    <noData v-else class="no-data"></noData>
  </div>
</template>
<script lang="ts" setup>
import { defineProps, defineEmits, watch, ref } from 'vue';
import G6 from '@antv/g6';
import { useStore } from 'vuex';
const store = useStore();
const emit = defineEmits(['g6Click', 'showEnlarge']);
const props = defineProps({
  rowList: {
    type: Object,
    default: () => {
      return {};
    },
  },
});
const loading = ref(true);
const g6Data = ref<any>({});
const g6Total = ref(0);
const lengthG6 = ref(0);
const lengthShow = ref(false);
watch(
  () => props.rowList,
  async (newVal, oldVal) => {
    await getSurfaceAnalysis();
  },
  {
    deep: true,
    immediate: true,
  },
);
const getSurfaceAnalysis = async () => {
  const { code, data } = await store.dispatch(
    'attack/getSurfaceAnalysis',
    props.rowList,
  );
  if (Number(code) === 0) {
    g6Data.value = data.data;
    g6Total.value = data.total;
    loading.value = false;
    lengthG6.value = g6Data.value.children.length;
    if (g6Data.value.children.length > 0) {
      emit('g6Click', data.data.vulId, g6Total.value);
      render();
      lengthShow.value = false;
    } else {
      lengthShow.value = true;
      emit('showEnlarge', false);
    }
  }
};
const render = async () => {
  // 文本超出隐藏
  // fittingString(字段, 最大长度, 字体大小)
  const fittingString = (str, maxWidth, fontSize) => {
    const ellipsis = '...';
    const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
    let currentWidth = 0;
    let res = str;
    const pattern = new RegExp('[\u4E00-\u9FA5]+'); // distinguish the Chinese charactors and letters
    str.split('').forEach((letter, i) => {
      if (currentWidth > maxWidth - ellipsisLength) return;
      if (pattern.test(letter)) {
        // Chinese charactors
        currentWidth += fontSize;
      } else {
        // get the width of single letter according to the fontSize
        currentWidth += G6.Util.getLetterWidth(letter, fontSize);
      }
      if (currentWidth > maxWidth - ellipsisLength) {
        res = `${str.substr(0, i)}${ellipsis}`;
      }
    });
    return res;
  };
  // todo 设置鼠标悬停显示详情操作
  const tooltip = new G6.Tooltip({
    offsetX: 10,
    offsetY: 10,
    getContent(e:any) {
      const outDiv = document.createElement('div');
      outDiv.style.width = '220px';
      outDiv.style.position = 'relative';
      outDiv.innerHTML = `
          <div>
          <p>${e.item.getModel().content}</p>
          </div>`;
      return outDiv;
    },
    itemTypes: ['node'],
  });
  // 自定义节点
  G6.registerNode(
    'tree-node',
    {
      drawShape: function drawShape(cfg:any, group:any) {
        const rect = group.addShape('rect', {
          attrs: {
            x: 0, // x 轴移动距离
            y: 0, // y 轴移动距离
            width: cfg.nood == 1 ? 170 : 190, // 宽
            height: 65, // 高
            // fill: '#666', // 背景色
            // stroke: '#666',// 边框色
          },
          name: 'big-rect-shape',
        });
        // 主节点
        if (cfg.depth == 0) {
          /* 盒子 */
          group.addShape('rect', {
            attrs: {
              fill: '#171717',
              x: 1,
              y: 5,
              width: 228,
              height: 52,
              radius: 4,
              cursor: 'pointer',
            },
            name: 'rect-shape',
          });
          /* 第一个图标 */
          group.addShape('image', {
            attrs: {
              x: 10,
              y: 18,
              height: 26,
              width: 26,
              img: require('@/static/images/retrieval/time.png'),
            },
            name: 'state-icon',
          });
          group.addShape('text', {
            attrs: {
              fill: '#8590B3',
              text: fittingString(cfg.content, 140, 14),
              x: 40,
              y: 33,
              fontSize: 14,
              textAlign: 'left',
              textBaseline: 'middle',
            },
            name: 'source-text-shape',
          });
        }
        // 节点2
        if (cfg.depth == 1) {
          group.addShape('rect', {
            attrs: {
              fill: ' #171717',
              x: 0,
              y: 5,
              width: 228,
              height: 52,
              radius: 4,
              cursor: 'pointer',
            },
            name: 'rect-shape',
          });
          /* 第一个图标 */
          group.addShape('image', {
            attrs: {
              x: 10,
              y: 16,
              height: 26,
              width: 26,
              img: require('@/static/images/retrieval/zise.png'),
            },
            name: 'state-icon',
          });
          /* 第一行字 */
          group.addShape('text', {
            attrs: {
              text: fittingString(cfg.content, 130, 12),
              x: 45,
              y: 30,
              fontSize: 14,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#8590B3',
              cursor: 'pointer',
            },
            name: 'text-shape',
          });
        }
        // 第3个节点
        if (cfg.depth == 2) {
          /* 盒子 */
          group.addShape('rect', {
            attrs: {
              fill: '#171717',
              x: 145,
              y: 5,
              width: 100,
              height: 52,
              radius: 4,
            },
            name: 'rect-shape',
          });
          /* 第一个图标 */

          group.addShape('image', {
            attrs: {
              x: 155,
              y: 18,
              height: 26,
              width: 26,
              img: require('@/static/images/retrieval/heike.png'),
            },
            name: 'state-icon',
          });
          group.addShape('text', {
            attrs: {
              text: cfg.content,
              x: 190,
              y: 33,
              fontSize: 14,
              textAlign: 'left',
              textBaseline: 'middle',
              fill: '#8590B3',
            },
            name: 'text-shape',
          });
        }
        return rect;
      },
    },
    'single-node',
  );


  const container:any = document.getElementById('container'); // 获取容器id
  const width = container.scrollWidth;
  const height = container.scrollHeight || 300; // 容器宽高
  const graph:any= new G6.TreeGraph({
    container,
    // width,
    // height,
    plugins: [tooltip], // 配置 Tooltip 插件
    // 设置画布的模式
    modes: {
      default: [
        'activate-relations',
        //   滚动
        // 'scroll-canvas'
        // // 拖拽画布；
        // 'drag-canvas',
        // // 缩放画布；
        // 'zoom-canvas',
        //  'drag-node'
      ],
    },

    // 默认状态下节点的配置，比如 type, size, color,会被写入的 data 覆盖
    defaultNode: {
      type: 'tree-node',
      // 指定边连入节点的连接点的位置（相对于该节点而言），可以为空
      anchorPoints: [
        [0, 0.5],
        [1, 0.5],
      ],
    },
    nodeStateStyles: {
      highlight: {
        // fill: "red",
      },
    },
    // 默认状态下边的配置
    defaultEdge: {
      // 指定边的类型，可以是内置边的类型名称，也可以是自定义边的名称。默认为 'line'
      type: 'cubic-horizontal',
      // 边的样式属性
      style: {
        // 边的颜色
        stroke: '#A3B1BF',
        // 开始箭头
        startArrow: {
          path: G6.Arrow.circle(2, 2), // 内置样式
          fill: '#A3B1BF', // 颜色
          d: 4, // 偏移距离
        },
      },
    },
    layout: {
      // 布局名称
      type: 'compactBox',
      direction: 'H',
      preventOverlap: true, // 防止节点重叠
      // 判断节点向左还是向右
      getSide: (d) => {
        // if (d.data.direction == '2') {
        //   return 'right';
        // }
        return 'left';
      },
      // 节点 id 的回调函数
      getId: function getId(d) {
        return d.id;
      },
      // 节点高度的回调函数
      getHeight: function getHeight() {
        return 40;
      },
      // 节点宽度的回调函数
      getWidth: function getWidth() {
        return 100;
      },
      // 节点纵向间距的回调函数
      getVGap: function getVGap() {
        return 20;
      },
      // 节点横向间距的回调函数
      getHGap: function getHGap() {
        return 110;
      },
    },
  });
  // 初始化的图数据
  graph.data(g6Data.value);
  // graph.data(this.dataList);
  // 根据提供的数据渲染视图。
  graph.render();
  // 缩放视窗窗口到一个固定比例
  graph.zoomTo(1);
  //  graph.fitView([0, 20]) // 自适应
  // 平移图到中心将对齐到画布中心，但不缩放
  graph.fitCenter();
  const elesLen = graph.save().children.length;
  const num = elesLen <= 2 ? 80 : 25;
  graph.moveTo(-80, num);

  // const getHeight = graph.cfg.layout.getHeight()
  const currentHeight = elesLen > 2 ? 90 * elesLen : height;
  container.style.height = currentHeight + 'px';
  graph.changeSize(width, currentHeight); // 重新设置高度

  if (typeof window !== 'undefined') {
    window.onresize = () => {
      if (!graph || graph.get('destroyed')) return;
      if (!container || !container.scrollWidth || !container.scrollHeight)
        return;
      graph.changeSize(container.scrollWidth, container.scrollHeight);
    };
  }
  const that = this; // 改变this指向
  graph.on('node:click', (e) => {
    const model = e.item.getModel();
    const item = e.item;
    if (model.depth == 1) {
      emit('g6Click', model.vulId, g6Total.value);
      // eslint-disable-next-line no-undef
      graph.setItemState(item, 'highlight', true);
    }
    if (model.depth == 0) {
      emit('g6Click', '', g6Total.value);
      // eslint-disable-next-line no-undef
      graph.setItemState(item, 'highlight', true);
    }
  });
  loading.value = false;
};
</script>
<style lang="scss" scoped>
.no-data {
  margin-top: $-v-spacing-horizontal-base;
}
</style>
